package edu.szte.ovrt.datahandler.core;

import java.io.Writer;

import org.junit.Test;

import static org.junit.Assert.assertNotNull;

import static org.powermock.api.easymock.PowerMock.*;
import edu.szte.ovrt.datahandler.model.*;

public class AbstractDocumentWriterTest {
	@Test
	public void testWriteDocumentNoSections() throws Exception {
		final Document document = new Document();

		final Class<AbstractDocumentWriter> ADWC = AbstractDocumentWriter.class;
		final AbstractDocumentWriter writer = createStrictMock(ADWC, ADWC.getDeclaredMethod("beginDocument", Document.class),
				ADWC.getDeclaredMethod("endDocument", Document.class));
		writer.beginDocument(document);
		expectLastCall();
		writer.endDocument(document);
		expectLastCall();
		replay(writer);

		writer.write(document);

		verify(writer);
	}

	@Test
	public void testWriteDocumentOneSection() throws Exception {
		final Document document = new Document();
		final Section section = document.newSection("");

		final Class<AbstractDocumentWriter> ADWC = AbstractDocumentWriter.class;
		final AbstractDocumentWriter writer = createStrictMock(ADWC, ADWC.getDeclaredMethod("beginDocument", Document.class),
				ADWC.getDeclaredMethod("endDocument", Document.class), ADWC.getDeclaredMethod("beginSection", Section.class),
				ADWC.getDeclaredMethod("endSection", Section.class));
		writer.beginDocument(document);
		expectLastCall();
		{
			writer.beginSection(section);
			expectLastCall();
			writer.endSection(section);
			expectLastCall();
		}
		writer.endDocument(document);
		expectLastCall();
		replay(writer);

		writer.write(document);

		verify(writer);
	}

	@Test
	public void testWriteDocumentMoreSections() throws Exception {
		final Document document = new Document();
		final Section section1 = document.newSection("");
		final Section section2 = document.newSection("");
		final Section section3 = document.newSection("");

		final Class<AbstractDocumentWriter> ADWC = AbstractDocumentWriter.class;
		final AbstractDocumentWriter writer = createStrictMock(ADWC, ADWC.getDeclaredMethod("beginDocument", Document.class),
				ADWC.getDeclaredMethod("endDocument", Document.class), ADWC.getDeclaredMethod("beginSection", Section.class),
				ADWC.getDeclaredMethod("endSection", Section.class));
		writer.beginDocument(document);
		expectLastCall();
		{
			writer.beginSection(section1);
			expectLastCall();
			writer.endSection(section1);
			expectLastCall();
			writer.beginSection(section2);
			expectLastCall();
			writer.endSection(section2);
			expectLastCall();
			writer.beginSection(section3);
			expectLastCall();
			writer.endSection(section3);
			expectLastCall();
		}
		writer.endDocument(document);
		expectLastCall();
		replay(writer);

		writer.write(document);

		verify(writer);
	}

	@Test
	public void testWriteSectionNoItems() throws Exception {
		final Section section = new Section(null, "");

		final Class<AbstractDocumentWriter> ADWC = AbstractDocumentWriter.class;
		final AbstractDocumentWriter writer = createStrictMock(ADWC, ADWC.getDeclaredMethod("beginSection", Section.class), ADWC
				.getDeclaredMethod("endSection", Section.class));
		writer.beginSection(section);
		expectLastCall();
		writer.endSection(section);
		expectLastCall();
		replay(writer);

		writer.write(section);

		verify(writer);
	}

	@Test
	public void testWriteSectionOneItem() throws Exception {
		final Section section = new Section(null, "");
		final Item item = section.newItem("key", "value");

		final Class<AbstractDocumentWriter> ADWC = AbstractDocumentWriter.class;
		final AbstractDocumentWriter writer = createStrictMock(ADWC, ADWC.getDeclaredMethod("beginSection", Section.class), ADWC
				.getDeclaredMethod("endSection", Section.class), ADWC.getDeclaredMethod("write", Item.class));
		writer.beginSection(section);
		expectLastCall();
		{
			writer.write(item);
			expectLastCall();
		}
		writer.endSection(section);
		expectLastCall();
		replay(writer);

		writer.write(section);

		verify(writer);
	}

	@Test
	public void testWriteSectionMoreItems() throws Exception {
		final Section section = new Section(null, "");
		final Item item1 = section.newItem("key1", "value1");
		final Item item2 = section.newItem("key2", "value2");
		final Item item3 = section.newItem("key3", "value3");

		final Class<AbstractDocumentWriter> ADWC = AbstractDocumentWriter.class;
		final AbstractDocumentWriter writer = createStrictMock(ADWC, ADWC.getDeclaredMethod("beginSection", Section.class), ADWC
				.getDeclaredMethod("endSection", Section.class), ADWC.getDeclaredMethod("write", Item.class));
		writer.beginSection(section);
		expectLastCall();
		{
			writer.write(item1);
			expectLastCall();
			writer.write(item2);
			expectLastCall();
			writer.write(item3);
			expectLastCall();
		}
		writer.endSection(section);
		expectLastCall();
		replay(writer);

		writer.write(section);

		verify(writer);
	}

	@Test
	public void testWriteFullDocument() throws Exception {
		final Document document = new Document();
		final Section section1 = document.newSection("section1");
		final Item item1 = section1.newItem("key1", "value1");

		final Section section2 = document.newSection("section2");
		final Item item2 = section2.newItem("key2", "value2");
		final Item item3 = section2.newItem("key3", "value3");

		final Class<AbstractDocumentWriter> ADWC = AbstractDocumentWriter.class;
		final AbstractDocumentWriter writer = createStrictMock(ADWC, ADWC.getDeclaredMethod("beginDocument", Document.class),
				ADWC.getDeclaredMethod("endDocument", Document.class), ADWC.getDeclaredMethod("beginSection", Section.class),
				ADWC.getDeclaredMethod("endSection", Section.class), ADWC.getDeclaredMethod("write", Item.class));
		writer.beginDocument(document);
		expectLastCall();
		{
			writer.beginSection(section1);
			expectLastCall();
			{
				writer.write(item1);
				expectLastCall();
			}
			writer.endSection(section1);
			expectLastCall();
			writer.beginSection(section2);
			expectLastCall();
			{
				writer.write(item2);
				expectLastCall();
				writer.write(item3);
				expectLastCall();
			}
			writer.endSection(section2);
			expectLastCall();
		}
		writer.endDocument(document);
		expectLastCall();
		replay(writer);

		writer.write(document);

		verify(writer);
	}

	@Test
	public void testConstructor() {
		final Writer writer = createMock(Writer.class);
		final AbstractDocumentWriter documentWriter = new AbstractDocumentWriter(writer) {
			@Override
			protected void beginDocument(final Document document) {/**/}

			@Override
			protected void beginSection(final Section section) {/**/}

			@Override
			protected void endDocument(final Document document) {/**/}

			@Override
			protected void endSection(final Section section) {/**/}

			@Override
			protected void write(final Item item) {/**/}
		};

		assertNotNull(documentWriter.m_writer);
	}
}
